﻿namespace WPCloudAppIteration2.Phone.ViewModel
{
    using System;
    using System.ComponentModel;
    using System.Globalization;
    using System.Windows;
    using System.Windows.Threading;
    using Microsoft.Samples.WindowsPhoneCloud.StorageClient;
    using WPCloudAppIteration2.Phone.Models;

    public class SampleDataDetailsPageViewModel : BaseViewModel
    {
        private readonly ITableServiceContext context;
        private readonly Dispatcher dispatcher;

        private SampleData sampleData;
        private string message;
        private bool isSaving = false;

        public SampleDataDetailsPageViewModel()
            : this(App.CloudClientFactory.ResolveTablesServiceContext("SampleData"), Deployment.Current.Dispatcher)
        {
        }

        public SampleDataDetailsPageViewModel(ITableServiceContext context, Dispatcher dispatcher)
        {
            this.context = context;
            this.dispatcher = dispatcher;
        }

        public event EventHandler SaveChangesSuccess;

        public SampleData SampleData
        {
            get
            {
                return this.sampleData;
            }

            set
            {
                if (this.sampleData != value)
                {
                    this.sampleData = value;
                    this.NotifyPropertyChanged("SampleData");
                }
            }
        }

        public string Message
        {
            get
            {
                return this.message;
            }

            set
            {
                if (this.message != value)
                {
                    this.message = value;
                    this.NotifyPropertyChanged("Message");
                }
            }
        }

        public bool IsSaving
        {
            get
            {
                return this.isSaving;
            }

            set
            {
                if (this.isSaving != value)
                {
                    this.isSaving = value;
                    this.NotifyPropertyChanged("IsSaving");
                }
            }
        }

        public void SetSampleDataModel(SampleData sampleData = null)
        {
            if (sampleData == null)
            {
                this.SampleData = new SampleData();
                try
                {
                    this.context.AddObject("SampleData", this.SampleData);
                }
                catch (Exception exception)
                {
                    var errorMessage = StorageClientExceptionParser.ParseDataServiceException(exception).Message;

                    this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", errorMessage);
                }
            }
            else
            {
                this.SampleData = sampleData;
                this.SampleData.PropertyChanged += this.OnUpdateSampleData;
            }
        }

        public void DeleteSampleData()
        {
            this.Message = "Deleting...";
            this.IsSaving = true;

            this.SampleData.PropertyChanged -= this.OnUpdateSampleData;

            try
            {
                this.context.DeleteObject(this.SampleData);
                this.context.BeginSaveChanges(this.OnBeginSaveChanges, null);
            }
            catch (Exception exception)
            {
                var errorMessage = StorageClientExceptionParser.ParseDataServiceException(exception).Message;

                this.IsSaving = false;
                this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", errorMessage);
            }
        }

        public void SaveSampleData()
        {
            this.Message = "Saving...";
            this.IsSaving = true;

            try
            {
                this.context.BeginSaveChanges(this.OnBeginSaveChanges, null);
            }
            catch (Exception exception)
            {
                var errorMessage = StorageClientExceptionParser.ParseDataServiceException(exception).Message;

                this.IsSaving = false;
                this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", errorMessage);
            }
        }

        private void OnUpdateSampleData(object sender, PropertyChangedEventArgs e)
        {
            this.SampleData.PropertyChanged -= this.OnUpdateSampleData;

            try
            {
                this.context.UpdateObject(this.SampleData);
            }
            catch (Exception exception)
            {
                var errorMessage = StorageClientExceptionParser.ParseDataServiceException(exception).Message;

                this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", errorMessage);
            }
        }

        private void OnBeginSaveChanges(IAsyncResult asyncResult)
        {
            this.dispatcher.BeginInvoke(
                () =>
                {
                    try
                    {
                        this.context.EndSaveChanges(asyncResult);

                        this.Message = "Changes saved successfully.";
                        this.IsSaving = false;

                        this.RaiseSaveChangesSuccess();
                    }
                    catch (Exception exception)
                    {
                        this.Message = string.Format(
                            CultureInfo.InvariantCulture,
                            "Error: {0}",
                            StorageClientExceptionParser.ParseDataServiceException(exception).Message);

                        this.IsSaving = false;
                    }
                });
        }

        private void RaiseSaveChangesSuccess()
        {
            var saveChangesSuccess = this.SaveChangesSuccess;
            if (saveChangesSuccess != null)
            {
                saveChangesSuccess(this, EventArgs.Empty);
            }
        }
    }
}
